#include "buffer.h"
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

#define FILE_SIZE 0x100000

struct account_linked_element {

  int account_number;
  int account_amount;
  struct account_linked_element * next;
  struct account_linked_element * prev;

} ;


typedef struct account_linked_element account;

int remove_node(account * curr){
  account * p, * n;
  p = (account *) curr->prev;
  n = (account *) curr->next;

  if(p!=NULL){
    p->next = (account *) n;
    }

    if(n!=NULL){
    n->prev = (account *) p;
    }

  free(curr);

  return 0;


}

account * head = NULL;
account * curr = NULL;



int process_request(request r){
 

  if(r.command == CREATE){
    account * newacc;
    newacc = (account *) malloc(sizeof(account));
    newacc->account_number = r.account;
    newacc->prev = NULL;
    newacc->next = head;
    head = newacc;
    printf("Created Account %d", r.account);
  } 

  account * active_acc;
  active_acc = head;

  while(active_acc->account_number != r.account && active_acc->next != NULL){
    active_acc = active_acc->next;
  } 
 
  if(active_acc->account_number != r.account){
    printf("The account you entered doesn't exist");
    return 0;
  }
 
  else if (r.command == DEPOSIT){
    active_acc->account_amount += r.amount;
    printf("Deposited $%d into account %d", r.amount, r.account);
  }

  else if (r.command == WITHDRAW){
    active_acc->account_amount += -r.amount;
    printf("Withdrew $%d from account %d", r.amount, r.account);
  }
 
  else if (r.command == BALANCE){
    int cur_amount = active_acc->account_amount;
    printf("Balance of account %d: $%d", r.account, active_acc->account_amount);
  }

  else if (r.command == CLOSE){
    remove_node(active_acc);    
    printf("Closed account %d", r.account);
  }  

  return 0;

}

int main(int argc, char *argv []){

  *argv++;

  void * map;
  int req_size = sizeof(map);
  int file = open(*argv++, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
  lseek(file, FILE_SIZE-1, SEEK_SET);

  write(file, "", 1); 


  buffer * b;
  //b = make_buf();  
  b = malloc(sizeof(buffer));
  map = mmap(NULL,  sizeof(buffer), PROT_READ | PROT_WRITE, MAP_SHARED, file, 0);

  sem_init(&b->empty, 0, 0);
  printf("%d\n", b->empty);
  sem_init(&b->full, 0, 10);
  sem_init(&b->lock, 0, 1);
  b->current_request = 0;
  int i;
    printf("%d\n", b->empty);

  request r;
  memcpy(map, b, sizeof(buffer)); 
    printf("%d\n", b->empty);
  b = (buffer *) map;



   printf("%d\n", b->empty);

  while(1){
   printf("waiting for empty\n");  
   printf("Empty is at %d\n", b->empty);
   sem_wait(&b->empty);
   sem_wait(&b->lock);
   b->current_request = b->current_request - 1;
   r = b->requests[b->current_request];
   sem_post(&r.event);

   printf("x\n"); 
   sem_post(&b->lock);
   sem_post(&b->empty);
}
  //sprintf((char*) map, "%d\n",1 );
  
  munmap(map, FILE_SIZE);
  return 0;
}
